#[derive(Debug, PartialEq)]
enum Token {
   Keyword(String),
   Identifier(String),
   Symbol(String),
   LiteralInt(i32),
   LiteralFloat(f64),
   Eof,
}

// TokenKind::Plus => Opreator::Add,
// TokenKind::Minus => Opreator::Subtract,
// TokenKind::Star => Opreator::Multiply,
// TokenKind::Slash => Opreator::Divide,
// TokenKind::Caret => Opreator::Power,

struct Lexer {
   input: String,
   position: usize,
}

impl Lexer {
   fn new(input: &str) -> Self {
      Self {
         input: input.to_string(),
         position: 0,
      }
   }

   fn next_token(&mut self) -> Option<Token> {
      self.skip_whitespace();

      match self.peek_char() {
         Some(c) => {
            if c.is_alphabetic() {
               let identifier = self.read_identifier();
               if is_keyword(&identifier) {
                  Some(Token::Keyword(identifier))
               } else {
                  Some(Token::Identifier(identifier))
               }
            } else if c.is_ascii_digit() {
               // Some(Token::Literal(self.read_number()))
               Some(self.read_number())
            } else if is_symbol(c) {
               self.next_char();
               Some(Token::Symbol(c.to_string()))
            } else {
               panic!("Unexpected character: {c}");
            }
         }
         None => Some(Token::Eof),
      }
   }

   fn peek_char(&self) -> Option<char> {
      self.input.chars().nth(self.position)
   }

   fn next_char(&mut self) -> Option<char> {
      let current_char = self.peek_char();
      self.position += 1;
      current_char
   }

   fn skip_whitespace(&mut self) {
      while let Some(c) = self.peek_char() {
         if !c.is_whitespace() {
            break;
         }
         self.next_char();
      }
   }

   fn read_identifier(&mut self) -> String {
      let mut identifier = String::new();
      while let Some(c) = self.peek_char() {
         if c.is_alphanumeric() || c == '_' {
            identifier.push(c);
            self.next_char();
         } else {
            break;
         }
      }

      identifier
   }

   fn read_number(&mut self) -> Token {
      // -------------------------------------------------------
      // let mut number = String::new();
      //
      // while let Some(c) = self.peek_char() {
      //     if c.is_ascii_digit() {
      //         number.push(c);
      //         self.next_char();
      //     } else {
      //         break;
      //     }
      // }
      //
      // number.parse().unwrap()
      // -------------------------------------------------------

      // -------------------------------------------------------
      // let mut number = String::new();
      // let mut has_decimal_point = false;
      //
      // while let Some(c) = self.peek_char() {
      //     if c.is_ascii_digit() {
      //         number.push(c);
      //         self.next_char();
      //     } else if c == '.' && !hass_decimal_point {
      //         number.push(c);
      //         has_decimal_point = true;
      //         self.next_char();
      //     } else {
      //         break;
      //     }
      // }
      //
      // if has_decimal_point {
      //     Token::LiteralFloat(number.parse().unwrap())
      // } else {
      //     Token::LiteralInt(number.parse().unwrap())
      // }
      // -------------------------------------------------------

      let mut number = String::new();
      let mut has_decimal_point = false;
      let mut has_exponent = false;

      // 解析小数
      while let Some(c) = self.peek_char() {
         if c.is_ascii_digit() {
            number.push(c);
            self.next_char();
         } else if c == '.' && !has_decimal_point {
            number.push(c);
            has_decimal_point = true;
            self.next_char();
         } else {
            break;
         }
      }

      // 解析科学记数法
      if let Some(c) = self.peek_char() {
         if c == 'e' || c == 'E' {
            number.push(c);
            self.next_char();
            has_exponent = true;

            // 是否有 + 或 -
            if let Some(sign) = self.peek_char() {
               if sign == '+' || sign == '-' {
                  number.push(sign);
                  self.next_char();
               }
            }

            // 读取指数
            while let Some(c) = self.peek_char() {
               if c.is_ascii_digit() {
                  number.push(c);
                  self.next_char();
               } else {
                  break;
               }
            }
         }
      }

      if has_decimal_point || has_exponent {
         Token::LiteralFloat(number.parse().unwrap())
      } else {
         Token::LiteralInt(number.parse().unwrap())
      }
   }
}

fn is_keyword(identifier: &str) -> bool {
   let keywords = ["if", "else", "true", "false"];
   keywords.contains(&identifier.to_lowercase().as_str())
}

fn is_symbol(c: char) -> bool {
   let symbols = ['=', '>', '<', '+', '-', '*', '/', '(', ')', ','];
   symbols.contains(&c)
}

fn main() {
   let input = "if age = 34.3 else true, false";
   let mut lexer = Lexer::new(input);
   while let Some(token) = lexer.next_token() {
      if token == Token::Eof {
         break;
      }
      println!("{token:?}");
   }
}
